package user

import (
	"context"
	"github.com/xinliangnote/go-gin-api/configs"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"strconv"
)

func NewModel() *User {
	return new(User)
}

func (p *User) GetUserByName(db *mongo.Client) (user *User, err error) {
	user = NewModel()
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	err = client.FindOne(context.TODO(), bson.D{{"username", p.Username}}).Decode(&user)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (p *User) CheckApikey(db *mongo.Client) (*User, error) {
	userInfo := new(User)
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	err := client.FindOne(context.TODO(), bson.D{{"apiKey", p.ApiKey}}).Decode(&userInfo)
	if err != nil {
		return nil, err
	}
	return userInfo, err
}

func (p *User) ChangePassword(db *mongo.Client) error {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	objId, _ := primitive.ObjectIDFromHex(p.Id)
	filter := bson.D{{"_id", objId}}
	update := bson.M{"$set": bson.M{
		"password": p.Password,
	}}
	_, err := client.UpdateOne(context.TODO(), filter, update)
	return err
}

func (p *User) GetUserById(db *mongo.Client) (user *User, err error) {
	user = NewModel()
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	objId, err := primitive.ObjectIDFromHex(p.Id)
	err = client.FindOne(context.TODO(), bson.D{{"_id", objId}}).Decode(&user)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (p *User) List(db *mongo.Client, pageIndex uint, pageSize uint, status string) ([]*User, error) {
	var userList []*User
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	findOptions := options.Find()
	skip := int64((pageIndex - 1) * pageSize)
	findOptions.SetSort(bson.D{{"_id", -1}})
	findOptions.SetSkip(skip)
	findOptions.SetLimit(int64(pageSize))

	filter := bson.M{"role": "0"}

	if p.Username != "" {
		filter["username"] = p.Username
	}
	if p.Email != "" {
		filter["email"] = p.Email
	}
	if status != "" {
		statusInt, _ := strconv.Atoi(status)
		filter["status"] = statusInt
	}
	find, err := client.Find(context.TODO(), filter, findOptions)
	if err != nil {
		return nil, err
	}
	err = find.All(context.TODO(), &userList)
	if err != nil {
		return nil, err
	}
	return userList, err
}

func (p *User) Count(db *mongo.Client) (int64, error) {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	count, err := client.CountDocuments(context.TODO(), bson.D{{"role", "0"}})
	return count, err
}

func (p *User) ChangeStatus(db *mongo.Client) error {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	objId, _ := primitive.ObjectIDFromHex(p.Id)
	filter := bson.D{{"_id", objId}}
	update := bson.M{"$set": bson.M{
		"status": p.Status,
	}}
	_, err := client.UpdateOne(context.TODO(), filter, update)
	return err
}

func (p *User) Create(db *mongo.Client) (string, error) {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	p.Role = "0"
	insertId, err := client.InsertOne(context.TODO(), p)

	return insertId.InsertedID.(primitive.ObjectID).Hex(), err
}

func (p *User) Update(db *mongo.Client) error {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	objId, _ := primitive.ObjectIDFromHex(p.Id)
	filter := bson.D{{"_id", objId}}
	update := bson.D{{"$set", bson.D{
		{"username", p.Username},
		{"email", p.Email},
		{"password", p.Password},
		{"maturityTime", p.MaturityTime},
		{"remark", p.Remark},
	}}}
	_, err := client.UpdateOne(context.TODO(), filter, update)
	return err
}

func (p *User) GetUserByEmail(db *mongo.Client) (user *User, err error) {
	user = NewModel()
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	err = client.FindOne(context.TODO(), bson.D{{"email", p.Email}}).Decode(&user)
	return user, err
}

func (p *User) ChangeLoginIp(db *mongo.Client) error {
	cfg := configs.Get().Mongodb
	client := db.Database(cfg.Config.Name).Collection("user")
	objId, _ := primitive.ObjectIDFromHex(p.Id)
	filter := bson.D{{"_id", objId}}

	update := bson.M{"$set": bson.M{
		"lastLoginIP": p.LastLoginIP,
	}}
	_, err := client.UpdateOne(context.TODO(), filter, update)
	return err
}
